home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / What's New? / Development Kits / Mac OS / USB DDK 1.4.6f4 / Examples / USBModem / ModemDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-25  |  40.9 KB  |  1,602 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ModemDriver.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-2000 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <DriverServices.h>
  13.  
  14. #include "Modem.h"
  15. #include "ModemDriver.h"
  16. #include "ShimSerialHAL.h"
  17.  
  18. enum
  19. {
  20.     kUSBv12    =    0x01200000
  21. };
  22.  
  23. static serPB         gSerialGlobals;
  24. static USBPB        syncPB, interruptPB, readPB, writePB, stallPB, delayPB;
  25. static UInt16        deadman = 20;
  26. static OSStatus        configerr = noErr;
  27. volatile Boolean    configured = false;
  28. UInt32                usbVersion = 0;
  29. UInt32                 PowerAvail = 0;
  30. Boolean                gUSBVersionNeedsBulkFixPresent;
  31.  
  32. /************************************************************************************/
  33. //
  34. //    CheckUSBVersion
  35. //
  36. //    Determines whether it's USB1.2 (less requires doing safe bulk calls)
  37. //
  38. /************************************************************************************/
  39. void    CheckUSBVersion(void)
  40. {
  41. OSStatus    err = 0;
  42.  
  43.     TraceMessage(0, "\pEntering CheckUSBVersion;g");
  44.     
  45.     err = Gestalt('usbv', (long*)&usbVersion);
  46.         
  47.     if (err == noErr)
  48.         gUSBVersionNeedsBulkFixPresent = (usbVersion < kUSBv12);
  49. }
  50.  
  51. /************************************************************************************/
  52. //
  53. //    SecondaryUSBBulkRead
  54. //
  55. //    USBBulkRead called at safe secondary int. time (USB 1.1 or earlier)
  56. //
  57. /************************************************************************************/
  58. OSStatus SecondaryUSBBulkRead(void *pb, void *result)
  59. {
  60.     *(OSStatus*)result = USBBulkRead((USBPB*)pb);
  61.     return noErr;
  62. }
  63.  
  64. /************************************************************************************/
  65. //
  66. //    SecondaryUSBBulkWrite
  67. //
  68. //    USBBulkWrite called at safe secondary int. time (USB 1.1 or earlier)
  69. //
  70. /************************************************************************************/
  71. OSStatus SecondaryUSBBulkWrite(void *pb, void *result)
  72. {
  73.     *(OSStatus*)result = USBBulkWrite((USBPB*)pb);
  74.     return noErr;
  75. }
  76.  
  77. /************************************************************************************/
  78. //
  79. //    SafeUSBBulkRead
  80. //
  81. //    Determines which version of the bulk read to call.
  82. //
  83. /************************************************************************************/
  84. OSStatus SafeUSBBulkRead(USBPB *pb)
  85. {
  86.     OSStatus    result;
  87.  
  88.     if (gUSBVersionNeedsBulkFixPresent)
  89.     {
  90.         // Use CallSecondaryInterruptHandler2 to call USBBulkRead if
  91.         // less than USB v1.2 present
  92.         CallSecondaryInterruptHandler2(SecondaryUSBBulkRead, nil, pb, &result);
  93.     }
  94.     else
  95.         result = USBBulkRead(pb);
  96.         
  97.     return result;
  98. }
  99.  
  100. /************************************************************************************/
  101. //
  102. //    SafeUSBBulkWrite
  103. //
  104. //    Determines which version of the bulk write to call.
  105. //
  106. /************************************************************************************/
  107. OSStatus SafeUSBBulkWrite(USBPB *pb)
  108. {
  109.     OSStatus    result;
  110.  
  111.     if (gUSBVersionNeedsBulkFixPresent)
  112.     {
  113.         // Use CallSecondaryInterruptHandler2 to call USBBulkWrite if
  114.         // less than USB v1.2 present
  115.         CallSecondaryInterruptHandler2(SecondaryUSBBulkWrite, nil, pb, &result);
  116.     }
  117.     else
  118.         result = USBBulkWrite(pb);
  119.         
  120.     return result;
  121. }
  122.  
  123. /************************************************************************************/
  124. //
  125. //    USBStatus
  126. //
  127. //    Determines which status call to make.
  128. //
  129. /************************************************************************************/
  130.  
  131. void USBStatus(UInt32 level, USBDeviceRef ref, void *pointer, UInt32 value)
  132. {
  133.     
  134.     if (usbVersion < kUSBv12)
  135.     {
  136.         USBExpertStatus(ref, pointer, value);
  137.     } else {
  138.         USBExpertStatusLevel(level, ref, pointer, value);
  139.     }
  140. }
  141.  
  142. /************************************************************************************/
  143. //
  144. //    immediateError
  145. //
  146. //    Determines whether it's an error or just pending.
  147. //
  148. /************************************************************************************/
  149.  
  150. static Boolean immediateError(OSStatus err)
  151. {
  152.     return ((err != kUSBPending) && (err != noErr));
  153. }
  154.  
  155. /************************************************************************************/
  156. //
  157. //    ConfigurationHandler
  158. //
  159. //    Configures the USB Serial Device (Modem).
  160. //
  161. /************************************************************************************/
  162.  
  163. static void ConfigurationHandler(USBPB *pb)
  164. {
  165.     serPB         *sp = &gSerialGlobals;
  166.  
  167. //    TraceMessage(0, kCRMName"- Entering ConfigurationHandler");
  168.     StatusMessage(sp->deviceRef, kCRMName"- Entering ConfigurationHandler", pb->usbRefcon);
  169.     
  170.     if(pb->usbStatus != noErr)
  171.     {
  172.         if (pb->usbStatus == kUSBDevicePowerProblem)
  173.         {
  174.             /* if it's a power problem we may as well go home now */
  175.             USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Device does not have enough power", pb->usbRefcon);
  176.             
  177.             USBExpertSetDevicePowerStatus(sp->deviceRef, 0, 0, kUSBDevicePower_BusPowerInsufficient, PowerAvail, kUSB500mAAvailable);  // TC: <USB67>
  178.             /* Mark port as errored */
  179.             configured = true;
  180.             configerr = pb->usbStatus;
  181.             return;
  182.         }
  183.         
  184.         if((sp->onError == kReset) && (sp->retries > 0))
  185.         {
  186.             /* no idea what to do now?? */
  187.             USBExpertFatalError(sp->deviceRef, pb->usbStatus, sp->errorString, pb->usbRefcon);
  188.             
  189.             /* Mark port as errored */
  190.             configured = true;
  191.             configerr = pb->usbStatus;
  192.         }
  193.         else
  194.         {
  195.             StatusMessage(sp->deviceRef, sp->errorString, pb->usbStatus);
  196.             pb->usbRefcon = sp->onError;
  197.  
  198.             USBClearPipeStallByReference(pb->usbReference);
  199.             
  200.             /* we'll delay coming back to here */
  201.             sp->retries--;
  202.  
  203.             pb->usbReqCount = 0;
  204.             USBDelay(pb);
  205.         }        
  206.         return;
  207.     }
  208.  
  209.     sp->onError = kReset;
  210.     pb->usbActCount = 0;    // If this comes back via the error delay, ActCount is set to ending frame
  211.     
  212.     do{switch(pb->usbRefcon++)
  213.     {
  214.         case kCommConfig:
  215.         
  216.             /* Need to find an interface with a communication class in it */
  217.             pb->usbClassType = kUSBCommClass;
  218.             pb->usbSubclass = 2;                        /* Abstract Control Model */
  219.             pb->usbProtocol = 1;                        /* v.25ter (Hayes AT Command set) */
  220.             pb->usb.cntl.WValue = 0;
  221.             pb->usb.cntl.WIndex = 0;
  222.             pb->usbReqCount = PowerAvail;
  223.             pb->usbBuffer = nil;
  224.             pb->usbFlags = 0;
  225.             
  226.             if (sp->retries > 0)
  227.             {
  228.                 sp->onError = kCommConfig;
  229.             } else {
  230.                 sp->onError = kReset;
  231.             }            
  232.             noteError(kCRMName"- Finding the Comm Class Interface");            
  233.             if(immediateError(configerr = USBFindNextInterface(pb)))
  234.             {
  235.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  236.                 configured = true;
  237.             }
  238.             
  239.         break;
  240.  
  241.         case kSetConfig:
  242.             StatusMessage(sp->deviceRef, kCRMName"- Configuration Number - ", pb->usb.cntl.WValue);
  243.             StatusMessage(sp->deviceRef, kCRMName"- Interface Number - ", pb->usb.cntl.WIndex);
  244.             
  245.             /* Remember the interface number */
  246.             sp->interfacenum = pb->usb.cntl.WIndex;
  247.             
  248.             pb->usbReqCount = 0;
  249.             
  250.             /* Open the device based on the config found */            
  251.             if (sp->retries > 0)
  252.             {
  253.                 sp->onError = kSetConfig;
  254.             } else {
  255.                 sp->onError = kReset;
  256.             }
  257.             noteError(kCRMName"- Setting the configuration");
  258.             if(immediateError(configerr = USBSetConfiguration(pb)))
  259.             {
  260.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  261.                 configured = true;
  262.             }
  263.         
  264.         break;
  265.         
  266.         case kGetCommInterface:
  267.             StatusMessage(sp->deviceRef, kCRMName"- Number of interfaces in Configuration - ", pb->usbOther);
  268.             
  269.             /* Get the interface reference number */
  270.             if (sp->retries > 0)
  271.             {
  272.                 sp->onError = kGetCommInterface;
  273.             } else {
  274.                 sp->onError = kReset;
  275.             }
  276.             pb->usbOther = 0;
  277.             
  278.             noteError(kCRMName"- Getting Comm Class interface");            
  279.             if(immediateError(configerr = USBNewInterfaceRef(pb)))
  280.             {
  281.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  282.                 configured = true;
  283.             }
  284.         
  285.         break;
  286.     
  287.         case kSetCommInterface:
  288.             StatusMessage(sp->deviceRef, kCRMName"- Comm. Interface Ref - ", pb->usbReference);
  289.             
  290.             /* Set the interface (Comm) */
  291.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBInterface);                        
  292.             pb->usb.cntl.BRequest = kUSBRqSetInterface;
  293.             pb->usb.cntl.WValue = 0;
  294.             pb->usb.cntl.WIndex = sp->interfacenum;
  295.             pb->usbReqCount = 0;
  296.             pb->usbBuffer = nil;
  297.             if (sp->retries > 0)
  298.             {
  299.                 sp->onError = kConfigureCommInterface;   // devices can return STALL (per sec. 9.4.10 of the USB 1.1 spec), if so just continue
  300.             } else {
  301.                 sp->onError = kReset;
  302.             }
  303.  
  304.             noteError(kCRMName"- Setting Comm Class interface");
  305.             if(immediateError(configerr = USBDeviceRequest(pb)))
  306.             {
  307.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  308.             }
  309.             break;
  310.  
  311.         case kConfigureCommInterface:
  312.             
  313.             /* configure the Comm Class interface */
  314.             if (sp->retries > 0)
  315.             {
  316.                 sp->onError = kConfigureCommInterface;
  317.             } else {
  318.                 sp->onError = kReset;
  319.             }
  320.             
  321.             noteError(kCRMName"- Configuring the Comm Class interface");
  322.             if(immediateError(configerr = USBConfigureInterface(pb)))
  323.             {    
  324.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  325.                 configured = true;
  326.             }
  327.             
  328.         break;
  329.         
  330.         case kGetInterruptEndpoint:
  331.             StatusMessage(sp->deviceRef, kCRMName"- Number of pipes in Interface - ", pb->usbOther);
  332.             
  333.             /* Get the Comm Class interrupt endpoint */
  334.             pb->usbFlags = kUSBIn;
  335.             pb->usbClassType = kUSBInterrupt;
  336.             if (sp->retries > 0)
  337.             {
  338.                 sp->onError = kGetInterruptEndpoint;
  339.             } else {
  340.                 sp->onError = kReset;
  341.             }
  342.             
  343.             noteError(kCRMName"- Finding the interrupt endpoint");
  344.             if(immediateError(configerr = USBFindNextPipe(pb)))
  345.             {    
  346.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  347.                 configured = true;
  348.             }
  349.             
  350.         break;
  351.         
  352.         case kDataConfig:
  353.             StatusMessage(sp->deviceRef, kCRMName"- Interrupt In Ref - ", pb->usbReference);
  354.             
  355.             /* Interrupt Endpoint is open - remember the ref */
  356.             sp->interrupt = pb->usbReference;
  357.             
  358.             /* Need to find an interface with a data class in it */
  359.             pb->usbClassType = kUSBDataClass;
  360.             pb->usbSubclass = 0;
  361.             pb->usbProtocol = 0;
  362.             pb->usb.cntl.WValue = 0;
  363.             pb->usb.cntl.WIndex = 0;
  364.             pb->usbReqCount = 0;
  365.             pb->usbBuffer = nil;
  366.             pb->usbFlags = 0;
  367.             pb->usbOther = 0;
  368.             pb->usbReference = sp->deviceRef;        // Set it back to the device
  369.             if (sp->retries > 0)
  370.             {
  371.                 sp->onError = kDataConfig;
  372.             } else {
  373.                 sp->onError = kReset;
  374.             }
  375.  
  376.             noteError(kCRMName"- Finding the Data Interface");
  377.             if(immediateError(configerr = USBFindNextInterface(pb)))
  378.             {
  379.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  380.                 configured = true;
  381.             }
  382.             
  383.         break;
  384.         
  385.         case kGetDataInterface:
  386.             StatusMessage(sp->deviceRef, kCRMName"- Configuration Number - ", pb->usb.cntl.WValue);
  387.             StatusMessage(sp->deviceRef, kCRMName"- Interface Number - ", pb->usb.cntl.WIndex);
  388.             
  389.             /* Remember the interface number */
  390.             sp->interfacenum = pb->usb.cntl.WIndex;
  391.             
  392.             /* Get the interface reference number */
  393.             if (sp->retries > 0)
  394.             {
  395.                 sp->onError = kGetDataInterface;
  396.             } else {
  397.                 sp->onError = kReset;
  398.             }            
  399.             pb->usbOther = 0;
  400.             
  401.             noteError(kCRMName"- Getting Data Class interface");
  402.             if(immediateError(configerr = USBNewInterfaceRef(pb)))
  403.             {
  404.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  405.                 configured = true;
  406.             }
  407.         
  408.         break;
  409.  
  410.         case kConfigureDataInterface:
  411.             StatusMessage(sp->deviceRef, kCRMName"- Data Interface Ref - ", pb->usbReference);
  412.             
  413.             /* configure the Data Class interface */
  414.             if (sp->retries > 0)
  415.             {
  416.                 sp->onError = kConfigureDataInterface;
  417.             } else {
  418.                 sp->onError = kReset;
  419.             }
  420.             
  421.             noteError(kCRMName"- Configuring the Data Class interface");
  422.             if(immediateError(configerr = USBConfigureInterface(pb)))
  423.             {    
  424.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  425.                 configured = true;
  426.             }
  427.             
  428.         break;
  429.             
  430.         case kGetBulkOutEndpoint:
  431.             StatusMessage(sp->deviceRef, kCRMName"- Number of pipes in Interface - ", pb->usbOther);
  432.             
  433.             /* Find the out endpoint */
  434.             pb->usbFlags = kUSBOut;
  435.             pb->usbClassType = kUSBBulk;
  436.             pb->usbSubclass = 0;            /* Find the first one */
  437.             if (sp->retries > 0)
  438.             {
  439.                 sp->onError = kGetBulkOutEndpoint;
  440.             } else {
  441.                 sp->onError = kReset;
  442.             }
  443.             
  444.             noteError(kCRMName"- Finding the bulk out endpoint");
  445.             if(immediateError(configerr = USBFindNextPipe(pb)))
  446.             {    
  447.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  448.                 configured = true;
  449.             }
  450.             
  451.         break;
  452.     
  453.         case kGetBulkInEndpoint:
  454.             StatusMessage(sp->deviceRef, kCRMName"- Bulk Out Endpoint - ", pb->usbReference);
  455.             
  456.             /* Out Endpoint is open - remember the ref */
  457.             sp->bulkOut = pb->usbReference;
  458.             
  459.             /* Find the in endpoint */
  460.             pb->usbFlags = kUSBIn;
  461.             pb->usbClassType = kUSBBulk;
  462.             pb->usbSubclass = 0;            /* Find the first one */
  463.             if (sp->retries > 0)
  464.             {
  465.                 sp->onError = kGetBulkInEndpoint;
  466.             } else {
  467.                 sp->onError = kReset;
  468.             }
  469.             
  470.             noteError(kCRMName"- Finding the bulk in endpoint");
  471.             if(immediateError(configerr = USBFindNextPipe(pb)))
  472.             {    
  473.                 USBExpertFatalError(sp->deviceRef, configerr, sp->errorString, 0);
  474.                 configured = true;
  475.             }
  476.             
  477.         break;
  478.     
  479.         case kConfigDone:
  480.             StatusMessage(sp->deviceRef, kCRMName"- Bulk In Endpoint - ", pb->usbReference);
  481.             
  482.             /* In Endpoint is open - remember the ref */
  483.             sp->bulkIn = pb->usbReference;
  484.             
  485.             StartStatusMonitor(sp->interrupt);
  486.             
  487.             // device is fully configured, ready for somebody to set the baud rate, etc.
  488.             // and start reading/writing to the bulk endpoints
  489.             syncPB.usbStatus = kAvailableStatus;
  490.             StatusMessage(sp->deviceRef, kCRMName"- Configuration complete.", 0);
  491.             configured = true;
  492.         break;
  493.     
  494.         default:
  495.             noteError(kCRMName"- Internal Error unused case in Configuration handler");            
  496.             StatusMessage(sp->deviceRef, sp->errorString, (pb->usbRefcon-1));
  497.             configured = true;
  498.             configerr = -1;
  499.         break;
  500.     }
  501.     break;    /* only execute once, unless continue used */
  502.     }while(1);    /* so case can be reentered with a continue */
  503. }
  504.  
  505. UInt16    statusData[8];
  506.  
  507. /************************************************************************************/
  508. //
  509. //    ResetInterruptPB
  510. //
  511. //    Re-initialize the interrupt PB.
  512. //
  513. /************************************************************************************/
  514.  
  515. static void ResetInterruptPB(USBPB *pb)
  516. {
  517.     pb->usbReqCount = 16;
  518.     pb->usbBuffer = &statusData;
  519.     pb->usbStatus = noErr;
  520. }
  521.  
  522. UInt8     Intrretries = 0;
  523.  
  524. /************************************************************************************/
  525. //
  526. //    interruptCompletion
  527. //
  528. //    Interrupt completion handler.
  529. //
  530. /************************************************************************************/
  531.  
  532. static void interruptCompletion(USBPB *pb)
  533. {
  534.     serPB         *sp = &gSerialGlobals;
  535.     OSStatus    err;
  536.     unsigned char        newErrs = 0;
  537.     ShimSerialGlobals    *globals = gGlobals;
  538.     
  539.     TraceMessage(0, kCRMName"- Entering interruptCompletion");
  540.     
  541.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  542.     {
  543.         if (pb->usbStatus != noErr)
  544.         {
  545.             StatusMessage(sp->deviceRef, kCRMName"- ModemDriver: interruptCompletion error ", pb->usbStatus);
  546.             if (pb->usbStatus == kUSBEndpointStallErr)
  547.             {
  548.                 ClearDevice();
  549.             }
  550.             USBClearPipeStallByReference(gSerialGlobals.interrupt);
  551.             
  552.             Intrretries++;
  553.             if (Intrretries > 10)
  554.                 return;                    // we'll just give up for now
  555.                 
  556.             DoDelay();
  557.  
  558.         } else {
  559.             Intrretries = 0;
  560.             TraceMessage(0, kCRMName"- Interrupt received");
  561.             if ((pb->usbActCount > 2) && ((statusData[0] & 0x00FF) == kSerialState))
  562.             {
  563.                 sp->modemUSBStatus = HostToUSBWord(statusData[4]);
  564.                 
  565.                 if (sp->modemUSBStatus & kUSBParityErr) 
  566.                     newErrs |= parityErr;
  567.                 if (sp->modemUSBStatus & kUSBFramingErr) 
  568.                     newErrs |= framingErr;
  569.                 if (sp->modemUSBStatus & kUSBHwOverRunErr) 
  570.                     newErrs |= hwOverrunErr;
  571.                     
  572.                 globals->serStat.cumErrs |= newErrs;
  573.                 StatusMessage(sp->deviceRef, kCRMName"- Modem Serial state - ", sp->modemUSBStatus);
  574.             }
  575.         }
  576.         
  577.         ResetInterruptPB(pb);
  578.  
  579.         if(immediateError(err = USBIntRead(pb)))
  580.         {
  581.             StatusMessage(sp->deviceRef, kCRMName"- Couldn't queue interrupt read!", err);
  582.         }
  583.     }
  584. }
  585.  
  586. /************************************************************************************/
  587. //
  588. //    StartStatusMonitor
  589. //
  590. //    Kick off the interrupt mechanism.
  591. //
  592. /************************************************************************************/
  593.  
  594. static void StartStatusMonitor(USBPipeRef interruptPipe)
  595. {
  596.     USBPB        *pb = &interruptPB;
  597.     serPB         *sp = &gSerialGlobals;
  598.     OSStatus    err;
  599.     
  600.     TraceMessage(0, kCRMName"- Entering StartStatusMonitor");
  601.     
  602.     InitializePB(pb, interruptPipe, interruptCompletion);
  603.  
  604.     ResetInterruptPB(pb);
  605.  
  606.     if(immediateError(err = USBIntRead(pb)))
  607.     {
  608.         StatusMessage(sp->deviceRef, kCRMName"- Couldn't start interrupt read!", err);
  609.     }        
  610.  
  611. }
  612.  
  613. /************************************************************************************/
  614. //
  615. //    syncCompletion
  616. //
  617. //    Completion handler for all sync (setup) requests.
  618. //
  619. /************************************************************************************/
  620.  
  621. static void syncCompletion(USBPB *pb)
  622. {
  623.     serPB     *sp = &gSerialGlobals;
  624.  
  625.     TraceMessage(0, kCRMName"- Entering syncCompletion");
  626.  
  627.     if (pb->usbStatus != noErr)
  628.     {
  629.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- ModemDriver: syncCompletion err for bRequest", pb->usb.cntl.BRequest);
  630.         if (pb->usbStatus == kUSBEndpointStallErr)
  631.         {
  632. //            ClearDevice();
  633.         }
  634.         USBClearPipeStallByReference(pb->usbReference);
  635.     }
  636.         
  637.     pb->usbStatus = kAvailableStatus;
  638. }
  639.  
  640. /************************************************************************************/
  641. //
  642. //    TimeoutPrevRequest
  643. //
  644. //    Timeout for all sync. requests.
  645. //
  646. /************************************************************************************/
  647.  
  648. Boolean TimeoutPrevRequest(void)
  649. {
  650.     USBPB        *pb = &syncPB;
  651.     serPB         *sp = &gSerialGlobals;
  652.     AbsoluteTime    startTime;
  653.     Duration        elapsedTime;
  654.  
  655.     if (pb->usbStatus == kAvailableStatus)
  656.         return false;
  657.     
  658.     startTime = UpTime();
  659.  
  660.     while (pb->usbStatus != kAvailableStatus){
  661.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  662.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  663.         if (elapsedTime > 100*durationMillisecond){
  664.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver, device request timeout - aborting", 0);
  665.             USBAbortPipeByReference(pb->usbReference);
  666.             return true;
  667.         }
  668.     }
  669.     return false;
  670. }
  671.  
  672. /************************************************************************************/
  673. //
  674. //    TimeoutStallRequest
  675. //
  676. //    Timeout for all stall clear requests.
  677. //
  678. /************************************************************************************/
  679.  
  680. Boolean TimeoutStallRequest(void)
  681. {
  682.     USBPB            *pb = &stallPB;
  683.     serPB             *sp = &gSerialGlobals;
  684.     AbsoluteTime    startTime;
  685.     Duration        elapsedTime;
  686.  
  687.     if (pb->usbStatus == kAvailableStatus)
  688.         return false;
  689.     
  690.     startTime = UpTime();
  691.  
  692.     while (pb->usbStatus != kAvailableStatus){
  693.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  694.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  695.         if (elapsedTime > 100*durationMillisecond){
  696.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver, Stall timeout - aborting", 0);
  697.             USBAbortPipeByReference(pb->usbReference);
  698.             return true;
  699.         }
  700.     }
  701.     return false;
  702. }
  703.  
  704. /************************************************************************************/
  705. //
  706. //    TimeoutDelayRequest
  707. //
  708. //    Timeout for delay requests.
  709. //
  710. /************************************************************************************/
  711.  
  712. Boolean TimeoutDelayRequest(void)
  713. {
  714.     USBPB            *pb = &delayPB;
  715.     serPB             *sp = &gSerialGlobals;
  716.     AbsoluteTime    startTime;
  717.     Duration        elapsedTime;
  718.  
  719.     if (pb->usbStatus == kAvailableStatus)
  720.         return false;
  721.     
  722.     startTime = UpTime();
  723.  
  724.     while (pb->usbStatus != kAvailableStatus){
  725.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  726.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  727.         if (elapsedTime > 100*durationMillisecond){
  728.             return true;
  729.         }
  730.     }
  731.     return false;
  732. }
  733.  
  734. /************************************************************************************/
  735. //
  736. //    USBSetBaudRate
  737. //
  738. //    Set up and send SetLineCoding request for baud rate only.
  739. //
  740. /************************************************************************************/
  741.  
  742. void USBSetBaudRate(UInt32 baudRate)
  743. {
  744.     USBPB        *pb = &syncPB;
  745.     serPB         *sp = &gSerialGlobals;
  746.     OSStatus     err;
  747.     UInt16        temp = 0;
  748.     UInt16        rateh;
  749.     Boolean        setdte = false;
  750.     
  751.     TraceMessage(0, kCRMName"- Entering USBSetBaudRate");
  752.     
  753.     if (TimeoutPrevRequest())
  754.         return;
  755.     
  756.     if (baudRate == kMaxBaudRate)        // We're going to lock to max for the moment
  757.     {
  758.     
  759.         // convert baudrate            I hate Intel...
  760.         temp = baudRate % 0x10000;
  761.         rateh = USBToHostWord(temp);
  762.         if (rateh != sp->Line_Settings.DTERate1)
  763.         {
  764.             sp->Line_Settings.DTERate1 = rateh;
  765.             setdte = true;
  766.         }
  767.         temp = baudRate / 0x10000;
  768.         rateh = USBToHostWord(temp);
  769.         if (rateh != sp->Line_Settings.DTERate2)
  770.         {
  771.             sp->Line_Settings.DTERate2 = rateh;
  772.             setdte = true;
  773.         }
  774.     
  775.         // Only do it if it's changing
  776.         if (setdte)
  777.         {        
  778.             pb->usbStatus = noErr;
  779.             pb->pbVersion = kUSBCurrentPBVersion;
  780.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);    
  781.             pb->usb.cntl.BRequest = kSetLineCoding;
  782.             pb->usb.cntl.WValue = 0;
  783.             pb->usb.cntl.WIndex = 1; 
  784.             pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  785.             pb->usbBuffer = &sp->Line_Settings;
  786.  
  787.             if(immediateError(err = USBDeviceRequest(pb)))
  788.             {
  789.                 StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting baud rate", err);
  790.                 pb->usbStatus = kAvailableStatus;
  791.             }
  792.         }
  793.     }
  794. }
  795.  
  796. /************************************************************************************/
  797. //
  798. //    USBSetLineCoding
  799. //
  800. //    Set up and send SetLineCoding Request for all settings.
  801. //
  802. /************************************************************************************/
  803.  
  804. void USBSetLineCoding(LineParms Line_Coding)
  805. {
  806.     USBPB        *pb = &syncPB;
  807.     serPB         *sp = &gSerialGlobals;
  808.     OSStatus     err;
  809.     Boolean        setcoding = false;
  810.     
  811.     TraceMessage(0, kCRMName"- Entering USBSetLineCoding");
  812.     
  813.     if (TimeoutPrevRequest())
  814.         return;
  815.         
  816.     // save the settings only if they've changed
  817.     if (Line_Coding.CharFormat != sp->Line_Settings.CharFormat)
  818.     {
  819.         sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  820.         setcoding = true;
  821.     }
  822.     if (Line_Coding.ParityType != sp->Line_Settings.ParityType)
  823.     {
  824.         sp->Line_Settings.ParityType = Line_Coding.ParityType;
  825.         setcoding = true;
  826.     }
  827.     if (Line_Coding.DataBits != sp->Line_Settings.DataBits)
  828.     {
  829.         sp->Line_Settings.DataBits = Line_Coding.DataBits;
  830.         setcoding = true;
  831.     }
  832.     
  833.     // Don't do this if they haven't changed
  834.     if (setcoding)
  835.     {
  836.         pb->usbStatus = noErr;
  837.         pb->pbVersion = kUSBCurrentPBVersion;
  838.         pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);                
  839.         pb->usb.cntl.BRequest = kSetLineCoding;
  840.         pb->usb.cntl.WValue = 0;
  841.         pb->usb.cntl.WIndex = 1; 
  842.         pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  843.         pb->usbBuffer = &sp->Line_Settings;
  844.  
  845.         if(immediateError(err = USBDeviceRequest(pb)))
  846.         {
  847.             StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Line Coding", err);
  848.             pb->usbStatus = kAvailableStatus;
  849.         }
  850.     }
  851. }
  852.  
  853. /************************************************************************************/
  854. //
  855. //    USBSetControlLineState
  856. //
  857. //    Set up and send SetControlLineState (DTR and RTS).
  858. //
  859. /************************************************************************************/
  860.  
  861. void USBSetControlLineState(void)
  862. {
  863.     USBPB        *pb = &syncPB;
  864.     serPB         *sp = &gSerialGlobals;
  865.     OSStatus     err;
  866.     
  867.     TraceMessage(0, kCRMName"- Entering USBSetControlLineState");
  868.     
  869.     if (TimeoutPrevRequest())
  870.         return;
  871.  
  872.     pb->usbStatus = noErr;
  873.     pb->pbVersion = kUSBCurrentPBVersion;
  874.     pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  875.     pb->usb.cntl.BRequest = kSetControlLineState;
  876.     pb->usb.cntl.WValue = sp->lineState;
  877.     pb->usb.cntl.WIndex = 1; 
  878.     pb->usbReqCount = 0;
  879.     pb->usbBuffer = 0;
  880.  
  881.     if(immediateError(err = USBDeviceRequest(pb)))
  882.     {
  883.         StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Control Line State", err);
  884.         pb->usbStatus = kAvailableStatus;
  885.     }
  886. }
  887.  
  888. /************************************************************************************/
  889. //
  890. //    USBSetDTRState
  891. //
  892. //    Set the DTR state.
  893. //
  894. /************************************************************************************/
  895.  
  896. void USBSetDTRState(Boolean state)
  897. {
  898.     serPB     *sp = &gSerialGlobals;
  899.  
  900.     TraceMessage(0, kCRMName"- Entering USBSetDTRState");
  901.  
  902.     if (state)
  903.     {
  904.         sp->lineState |= kDTROn;
  905.     } else {
  906.         if (!sp->DTRClose)
  907.             sp->lineState &= (kDTROff + kRTSOn);
  908.     }
  909. }
  910.  
  911. /************************************************************************************/
  912. //
  913. //    USBSetRTSState
  914. //
  915. //    Set the RTS state.
  916. //
  917. /************************************************************************************/
  918.  
  919. void USBSetRTSState(Boolean state)
  920. {
  921.     serPB     *sp = &gSerialGlobals;
  922.  
  923.     TraceMessage(0, kCRMName"- Entering USBSetRTSState");
  924.  
  925.     if (state)
  926.     {
  927.         sp->lineState |= kRTSOn;
  928.     } else {
  929.         sp->lineState &= (kRTSOff + kDTROn);
  930.     }
  931. }
  932.  
  933. /************************************************************************************/
  934. //
  935. //    USBSendBreak
  936. //
  937. //    Set up and send break request.
  938. //
  939. /************************************************************************************/
  940.  
  941. void USBSendBreak(Boolean state)
  942. {
  943.     USBPB        *pb = &syncPB;
  944.     serPB         *sp = &gSerialGlobals;
  945.     OSStatus     err;
  946.     
  947.     TraceMessage(0, kCRMName"- Entering USBSendBreak");
  948.     
  949.     if (TimeoutPrevRequest())
  950.         return;
  951.  
  952.     pb->usbStatus = noErr;
  953.     pb->pbVersion = kUSBCurrentPBVersion;
  954.     pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  955.     pb->usb.cntl.BRequest = kSendBreak;
  956.     if (state)
  957.     {
  958.         pb->usb.cntl.WValue = kBreakOn;
  959.     } 
  960.     else 
  961.     {
  962.         pb->usb.cntl.WValue = kBreakOff;
  963.     }
  964.     pb->usb.cntl.WIndex = 1; 
  965.     pb->usbReqCount = 0;
  966.     pb->usbBuffer = 0;
  967.  
  968.     if(immediateError(err = USBDeviceRequest(pb)))
  969.     {
  970.         StatusMessage(sp->deviceRef, kCRMName"- Modem driver Setting Break State", err);
  971.         pb->usbStatus = kAvailableStatus;
  972.     }
  973. }
  974.  
  975. /************************************************************************************/
  976. //
  977. //    USBSetCloseDTR
  978. //
  979. //    Set the state of DTR on close.
  980. //
  981. /************************************************************************************/
  982.  
  983. void USBSetCloseDTR(void)
  984. {
  985.     serPB     *sp = &gSerialGlobals;
  986.  
  987.     TraceMessage(0, kCRMName"- Entering USBSetCloseDTR");
  988.  
  989.     sp->DTRClose = true;
  990. }
  991.  
  992. /************************************************************************************/
  993. //
  994. //    USBGetDCDValue
  995. //
  996. //    Gets the current state of CD.
  997. //
  998. /************************************************************************************/
  999.  
  1000. UInt8 USBGetDCDValue(void)
  1001. {
  1002.     serPB     *sp = &gSerialGlobals;
  1003.     UInt8    dcd = 0;
  1004.  
  1005.     TraceMessage(0, kCRMName"- Entering USBGetDCDValue");
  1006.  
  1007.     if (sp->modemUSBStatus & kUSBDCD) 
  1008.         dcd = 1;
  1009.         
  1010.     return dcd;
  1011. }
  1012.  
  1013. /************************************************************************************/
  1014. //
  1015. //    ModemDriverEntry
  1016. //
  1017. //    Initializes and starts the whole show.
  1018. //
  1019. /************************************************************************************/
  1020.  
  1021. OSStatus modemDriverEntry(USBDeviceRef device, USBDeviceDescriptor *desc, UInt32 bPower)
  1022. {
  1023. static Boolean                 beenThereDoneThat = false;
  1024. static USBDeviceDescriptor     ourDeviceDescriptor;
  1025.  
  1026. //    DebugMessage(kCRMName"- Entering modemDriverEntry - Sync. point");
  1027.     TraceMessage(0, kCRMName"- Entering modemDriverEntry");
  1028.         
  1029.     if(beenThereDoneThat)
  1030.     {
  1031.         StatusMessage(device, kCRMName"- Modem driver called second time", 0);
  1032.         return -1;
  1033.     }
  1034.     beenThereDoneThat = true;
  1035.     
  1036.     ourDeviceDescriptor = *desc;
  1037.     gSerialGlobals.deviceDescriptor = &ourDeviceDescriptor;
  1038.     gSerialGlobals.deviceRef = device;
  1039.     PowerAvail = bPower;
  1040.     
  1041.     InitializePB(&syncPB, device, syncCompletion);
  1042.     InitializePB(&stallPB, device, stallHandler);
  1043.     stallPB.usbStatus = kAvailableStatus;
  1044.     InitializePB(&delayPB, device, delayHandler);
  1045.     delayPB.usbStatus = kAvailableStatus;
  1046.  
  1047.     InitializePB(&gSerialGlobals.pb, device, ConfigurationHandler);
  1048.     gSerialGlobals.pb.usbRefcon = kCommConfig;    // Where we start from (kReset used for errors)
  1049.     gSerialGlobals.pb.usbBuffer = nil;
  1050.  
  1051.     gSerialGlobals.retries = 3;                // Let's keep it reasonable for now
  1052.     
  1053.     CheckUSBVersion();                        // Establish version and bulk fix flag before we start
  1054.     
  1055.     ConfigurationHandler(&gSerialGlobals.pb);
  1056.     
  1057.     if (configerr == 1)                        // pending's ok
  1058.     {
  1059.         return noErr;
  1060.     } else {
  1061.         return configerr;
  1062.     }
  1063. }
  1064.  
  1065. /************************************************************************************/
  1066. //
  1067. //    InitializePB
  1068. //
  1069. //    Initial a parameter block.
  1070. //
  1071. /************************************************************************************/
  1072.  
  1073. static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler)
  1074. {
  1075.     pb->pbVersion = kUSBCurrentPBVersion;
  1076.     pb->pbLength = sizeof(*pb);
  1077.     pb->usbReference = ref;
  1078.     pb->usbCompletion = handler;
  1079.     pb->usbStatus = noErr;
  1080.     
  1081. }
  1082.  
  1083. static errCount, readActive = false;
  1084.  
  1085. /************************************************************************************/
  1086. //
  1087. //    readCompletion
  1088. //
  1089. //    Completion handler for USB reads.
  1090. //
  1091. /************************************************************************************/
  1092.  
  1093. void readCompletion(USBPB *pb)
  1094. {
  1095.  
  1096.     TraceMessage(0,kCRMName"- Entering readCompletion");
  1097.     
  1098.     readActive = false;
  1099.     
  1100.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  1101.     {
  1102.         if (pb->usbStatus == noErr)
  1103.         {
  1104.             LogData(kUSBIn, pb->usbActCount, pb->usbBuffer);
  1105.             HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  1106.         } else {
  1107.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Read completion error ", pb->usbStatus);
  1108.                 
  1109.             if ((pb->usbStatus != kUSBUnderRunErr) && errCount++ < 10)
  1110.                 StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Read completion error ", pb->usbStatus);
  1111.                 
  1112.             if (pb->usbStatus == kUSBEndpointStallErr)
  1113.             {
  1114. //                ClearDevice();
  1115.             }
  1116.             USBClearPipeStallByReference(gSerialGlobals.bulkIn);
  1117.             if (pb->usbActCount > 0)
  1118.             {
  1119.                 LogData(kUSBIn, pb->usbActCount, pb->usbBuffer);
  1120.                 HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  1121.             }
  1122.         }
  1123.     
  1124.         USBStartReadPolling();
  1125.     }
  1126. }
  1127.  
  1128. static UInt8    ioBuffer[64];
  1129.  
  1130. /************************************************************************************/
  1131. //
  1132. //    USBStartReadPolling
  1133. //
  1134. //    Start the USB read mechanism.
  1135. //
  1136. /************************************************************************************/
  1137.  
  1138. void USBStartReadPolling(void)
  1139. {
  1140.     OSStatus status;
  1141.     
  1142.     TraceMessage(0,kCRMName"- Entering USBStartReadPolling");
  1143.     
  1144.     if (gSerialGlobals.bulkIn && !readActive){
  1145.         InitializePB(&readPB, gSerialGlobals.bulkIn, readCompletion);
  1146.         readPB.usbBuffer = ioBuffer;
  1147.         readPB.usbReqCount = sizeof(ioBuffer);
  1148.         if(immediateError(status = SafeUSBBulkRead(&readPB)))
  1149. //        if(immediateError(status = USBBulkRead(&readPB)))
  1150.         {
  1151.             USBExpertFatalError(gSerialGlobals.deviceRef, status, kCRMName"- ModemDriver: Couldn't start read polling", 0);
  1152.             return;
  1153.         }
  1154.         readActive = true;
  1155.     }
  1156. }
  1157.  
  1158. /************************************************************************************/
  1159. //
  1160. //    USBStopReadPolling
  1161. //
  1162. //    You guessed it stop the USB read mechanism.
  1163. //
  1164. /************************************************************************************/
  1165.  
  1166. void USBStopReadPolling()
  1167. {
  1168.     StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Aborting Bulk-in pipe", 0);
  1169.  
  1170.     if (gSerialGlobals.bulkIn){
  1171.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  1172.     }
  1173. }
  1174.  
  1175. static    UInt32    writeActive;
  1176.  
  1177. /************************************************************************************/
  1178. //
  1179. //    writeCompletion
  1180. //
  1181. //    USB write completion handler.
  1182. //
  1183. /************************************************************************************/
  1184.  
  1185. void writeCompletion(USBPB *pb)
  1186. {
  1187.     IOParam    *iopb;
  1188.     
  1189.     TraceMessage(0, kCRMName"- Entering writeCompletion");
  1190.     
  1191.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  1192.     {
  1193.         if (pb->usbStatus != noErr) 
  1194.         {
  1195.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Write Failed", pb->usbStatus);
  1196.             
  1197.             if (pb->usbStatus == kUSBEndpointStallErr)
  1198.             {
  1199. //                ClearDevice();
  1200.             }
  1201.             USBClearPipeStallByReference(pb->usbReference);
  1202.         }
  1203.     }
  1204.     writeActive--;
  1205.     gGlobals->pbOut = nil;
  1206.     iopb = (IOParam *)pb->usbRefcon;
  1207.     iopb->ioActCount = pb->usbActCount;
  1208.     
  1209.     ShimIOComplete((union ParamBlockRec *)iopb, pb->usbStatus ? ioErr : 0);
  1210.  
  1211. }
  1212.  
  1213. /************************************************************************************/
  1214. //
  1215. //    USBSerialWrite
  1216. //
  1217. //    USB serial write routine.
  1218. //
  1219. /************************************************************************************/
  1220.  
  1221. OSStatus USBSerialWrite(IOParam *pb)
  1222. {
  1223.     OSStatus     status = noErr;
  1224.     
  1225.     TraceMessage(0, kCRMName"- Entering USBSerialWrite");
  1226.     
  1227.     if (writeActive){
  1228.         StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Overlapping writes!", writePB.usbStatus);
  1229.         status = ioErr;
  1230.     } else if (gSerialGlobals.bulkOut){
  1231.         
  1232.         InitializePB(&writePB, gSerialGlobals.bulkOut, writeCompletion);
  1233.         writePB.usbRefcon = (UInt32)pb;
  1234.         writePB.usbBuffer = pb->ioBuffer;
  1235.         writePB.usbReqCount = pb->ioReqCount;
  1236.         
  1237.         LogData(kUSBOut, writePB.usbReqCount, writePB.usbBuffer);
  1238.         
  1239.         if(immediateError(status = SafeUSBBulkWrite(&writePB)))
  1240. //        if(immediateError(status = USBBulkWrite(&writePB)))
  1241.         {
  1242.             StatusMessage(gSerialGlobals.deviceRef, kCRMName"- ModemDriver: Couldn't start write", status);
  1243.         } else {
  1244.             writeActive++;
  1245.             status = 1;                        // pending
  1246.         }
  1247.     } else {
  1248.         status = ioErr;
  1249.     }
  1250.     return status;
  1251. }
  1252.  
  1253. /************************************************************************************/
  1254. //
  1255. //    KillUSBIO
  1256. //
  1257. //    Kill all USB io operations in progress.
  1258. //
  1259. /************************************************************************************/
  1260.  
  1261. void KillUSBIO(void)
  1262. {
  1263.     IOParam             *pb;
  1264.     ShimSerialGlobals     *globals = gGlobals;
  1265.     
  1266.     StatusMessage(gSerialGlobals.deviceRef, kCRMName"- Modem: Killing all USB IO", 0);
  1267.  
  1268.     if (gSerialGlobals.bulkIn){
  1269.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  1270.         gSerialGlobals.bulkIn = nil;
  1271.     }
  1272.     if (gSerialGlobals.bulkOut){
  1273.         USBAbortPipeByReference(gSerialGlobals.bulkOut);
  1274.         gSerialGlobals.bulkOut = nil;
  1275.     }
  1276.     if (gSerialGlobals.interrupt){
  1277.         USBAbortPipeByReference(gSerialGlobals.interrupt);
  1278.         gSerialGlobals.interrupt = nil;
  1279.     }
  1280.     
  1281.     pb = (IOParam *)globals->pbIn;
  1282.     if (pb) {
  1283.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1284.         globals->pbIn = nil;
  1285.     }
  1286.     pb = (IOParam *)globals->pbOut;
  1287.     if (pb) {
  1288.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1289.         globals->pbOut = nil;
  1290.     }
  1291. }
  1292.  
  1293. /************************************************************************************/
  1294. //
  1295. //    InitLineCoding
  1296. //
  1297. //    Store the initial line settings.
  1298. //
  1299. /************************************************************************************/
  1300.  
  1301. void InitLineCoding(LineParms Line_Coding)
  1302. {
  1303.     serPB     *sp = &gSerialGlobals;
  1304.     
  1305.     TraceMessage(0, kCRMName"- Entering InitLineCoding");
  1306.         
  1307.     // save the settings
  1308.     sp->Line_Settings.DTERate1 = Line_Coding.DTERate1;
  1309.     sp->Line_Settings.DTERate2 = Line_Coding.DTERate2;
  1310.     sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  1311.     sp->Line_Settings.ParityType = Line_Coding.ParityType;
  1312.     sp->Line_Settings.DataBits = Line_Coding.DataBits;
  1313. }
  1314.  
  1315. /************************************************************************************/
  1316. //
  1317. //    DoDelay
  1318. //
  1319. //    Set up to do a USB delay.
  1320. //
  1321. /************************************************************************************/
  1322.  
  1323. void DoDelay(void)
  1324. {
  1325. serPB     *sp = &gSerialGlobals;
  1326.     
  1327.     TraceMessage(0, kCRMName"- Entering DoDelay");
  1328.     
  1329.     if (TimeoutDelayRequest())
  1330.         return;
  1331.             
  1332.     delayPB.usbStatus = noErr;
  1333.     delayPB.usbReference = sp->deviceRef;
  1334.     delayPB.usbRefcon = 1;
  1335.     delayPB.usbReqCount = 5;            // ~5ms (actually 5 frames at 1ms each)
  1336.     USBDelay(&delayPB);    
  1337. }
  1338.  
  1339. /************************************************************************************/
  1340. //
  1341. //    delayHandler
  1342. //
  1343. //    Completion handler for USB delay.
  1344. //
  1345. /************************************************************************************/
  1346.  
  1347. static void delayHandler(USBPB *pb)
  1348. {
  1349. serPB     *sp = &gSerialGlobals;
  1350.  
  1351.     TraceMessage(0, kCRMName"- Entering delayHandler");
  1352.  
  1353.     if (pb->usbStatus != noErr)
  1354.         StatusMessage(sp->deviceRef, kCRMName"- ModemDriver: Delay fail?", pb->usbStatus);
  1355.  
  1356.     pb->usbStatus = kAvailableStatus;
  1357. }
  1358.  
  1359. /************************************************************************************/
  1360. //
  1361. //    ClearDevice
  1362. //
  1363. //    Set up and send ClearFeature request (for stall).
  1364. //
  1365. /************************************************************************************/
  1366.  
  1367. void ClearDevice(void)
  1368. {
  1369. serPB     *sp = &gSerialGlobals;
  1370.  
  1371.     TraceMessage(0, kCRMName"- Entering ClearDevice");
  1372.     
  1373.     if (TimeoutStallRequest())
  1374.         return;
  1375.         
  1376.     stallPB.usbStatus = noErr;
  1377.     stallPB.usbReference = sp->deviceRef;
  1378.     stallPB.usbRefcon = kEndpointStall;
  1379.     stallHandler(&stallPB);
  1380. }
  1381.  
  1382. /************************************************************************************/
  1383. //
  1384. //    stallHandler
  1385. //
  1386. //    Completion handler for clear device/stall.
  1387. //
  1388. /************************************************************************************/
  1389.  
  1390. static void stallHandler(USBPB *pb)
  1391. {
  1392. serPB         *sp = &gSerialGlobals;
  1393. OSStatus    err = 0;
  1394.  
  1395.     TraceMessage(0, kCRMName"- Entering StallHandler");
  1396.     
  1397.     if (pb->usbStatus != noErr)
  1398.     {
  1399.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: Stall fail?", pb->usbRefcon);
  1400.         return;
  1401.     }
  1402.     
  1403.     // May have to do more here (like find out which endpoint is stalled) which is why an FSM is used
  1404.     // For the moment it's the Comm Class endpoint 0 which we'll try to clear (interupptComplete only for now)
  1405.     do{switch(pb->usbRefcon++)
  1406.     {
  1407.         case kEndpointStall:
  1408.             pb->usbStatus = noErr;
  1409.             pb->usbReference = sp->deviceRef;
  1410.             pb->pbVersion = kUSBCurrentPBVersion;    
  1411.             pb->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
  1412.     
  1413.             pb->usb.cntl.BRequest = kUSBRqClearFeature;
  1414.             pb->usb.cntl.WValue = 0;                        // Endpoint stall
  1415.             pb->usb.cntl.WIndex = 0;
  1416.             pb->usbReqCount = 0;
  1417.             pb->usbBuffer = nil;
  1418.  
  1419.             if(immediateError(err = USBDeviceRequest(pb)))
  1420.             {
  1421.                 StatusMessage(sp->deviceRef, kCRMName"- Driver clearing device stall error", err);
  1422.             }
  1423.         break;
  1424.         
  1425.         case kStallDone:
  1426.         // stall should now be cleared
  1427.             if (pb->usbStatus != noErr)
  1428.                 USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: stall handler err for bRequest", pb->usb.cntl.BRequest);
  1429.     
  1430.             pb->usbStatus = kAvailableStatus;
  1431.         break;
  1432.         
  1433.         default:
  1434.             StatusMessage(sp->deviceRef, kCRMName"- Internal Error unused case in stall handler", (pb->usbRefcon-1));
  1435.         break;
  1436.     }
  1437.     break;    /* only execute once, unless continue used */
  1438.     }while(1);    /* so case can be reentered with a continue */
  1439. }
  1440.  
  1441. /************************************************************************************/
  1442. //
  1443. //    ResetDevice
  1444. //
  1445. //    Resets the device (uses same PB as ClearStall).
  1446. //
  1447. /************************************************************************************/
  1448.  
  1449. void ResetDevice(void)
  1450. {
  1451. serPB     *sp = &gSerialGlobals;
  1452.  
  1453.     TraceMessage(0, kCRMName"- Entering ResetDevice");
  1454.     
  1455.     if (TimeoutStallRequest())
  1456.         return;
  1457.         
  1458.     stallPB.usbStatus = noErr;
  1459.     stallPB.usbReference = sp->deviceRef;
  1460.     stallPB.usbRefcon = kResetDevice;
  1461.     ResetHandler(&stallPB);
  1462. }
  1463.  
  1464. /************************************************************************************/
  1465. //
  1466. //    ResetHandler
  1467. //
  1468. //    Completion handler for Reset device.
  1469. //
  1470. /************************************************************************************/
  1471.  
  1472. static void ResetHandler(USBPB *pb)
  1473. {
  1474. serPB         *sp = &gSerialGlobals;
  1475. OSStatus    err = 0;
  1476.  
  1477.     TraceMessage(0, kCRMName"- Entering ResetHandler");
  1478.     
  1479.     if (pb->usbStatus != noErr)
  1480.     {
  1481.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: Reset fail?", pb->usbRefcon);
  1482.         return;
  1483.     }
  1484.     
  1485.     // May have to do a couple of things here 
  1486.     do{switch(pb->usbRefcon++)
  1487.     {
  1488.         case kResetDevice:
  1489.             pb->usbStatus = noErr;
  1490.             pb->usbReference = sp->deviceRef;
  1491.             pb->pbVersion = kUSBCurrentPBVersion;    
  1492.             pb->usb.cntl.WValue = 0;
  1493.             pb->usb.cntl.WIndex = 0;
  1494.             pb->usbReqCount = 0;
  1495.             pb->usbBuffer = nil;
  1496.             pb->usbFlags = 0;
  1497.  
  1498.             if(immediateError(err = USBResetDevice(pb)))
  1499.             {
  1500.                 StatusMessage(sp->deviceRef, kCRMName"- Driver reset device error", err);
  1501.             }
  1502.         break;
  1503.         
  1504.         case kResetDone:
  1505.             if (pb->usbStatus != noErr)
  1506.                 USBExpertFatalError(sp->deviceRef, pb->usbStatus, kCRMName"- Driver: reset handler err ", pb->usbRefcon);
  1507.     
  1508.             pb->usbStatus = kAvailableStatus;
  1509.         break;
  1510.         
  1511.         default:
  1512.             StatusMessage(sp->deviceRef, kCRMName"- Internal Error unused case in reset handler", (pb->usbRefcon-1));
  1513.         break;
  1514.     }
  1515.     break;    /* only execute once, unless continue used */
  1516.     }while(1);    /* so case can be reentered with a continue */
  1517. }
  1518.  
  1519. /************************************************************************************/
  1520. //
  1521. //    Asciify
  1522. //
  1523. //    Convert to Ascii character
  1524. //
  1525. /************************************************************************************/
  1526.  
  1527. UInt8 Asciify(UInt8 i)
  1528. {
  1529.  
  1530.     i &= 0xF;
  1531.     if ( i < 10 )
  1532.          return( '0' + i );
  1533.     else return( 55  + i );
  1534.     
  1535. }
  1536.  
  1537. #if ((DebugOn > 0) && (LogOn > 0))
  1538.  
  1539. #define dumplen        16        // Set this to the number of bytes to dump and the rest should work out correct
  1540.  
  1541. #define buflen        ((dumplen*2)+dumplen)+3
  1542. #define Asciistart    (dumplen*2)+3
  1543.  
  1544. /************************************************************************************/
  1545. //
  1546. //    USBLogData
  1547. //
  1548. //    Dumps the requested amount of data to the USB Expert log.
  1549. //
  1550. /************************************************************************************/
  1551.  
  1552. void USBLogData(UInt8 Dir, UInt32 Count, UInt8 *buf)
  1553. {
  1554.     UInt8        wlen, i, Aspnt, Hxpnt;
  1555.     UInt8        wchr;
  1556.     UInt8        LocBuf[buflen];
  1557.  
  1558.     for ( i=1; i<=buflen; i++)
  1559.     {
  1560.         LocBuf[i] = 0x20;
  1561.     }
  1562.     
  1563.     if (Dir == kUSBIn)
  1564.     {
  1565.         TraceMessage(1, kCRMName"- Read Complete");
  1566.     } else {
  1567.         if (Dir == kUSBOut)
  1568.         {
  1569.             TraceMessage(1, kCRMName"- Write");
  1570.         }
  1571.     }
  1572.  
  1573.     if (Count > dumplen)
  1574.     {
  1575.         wlen = dumplen;
  1576.     } else {
  1577.         wlen = Count;
  1578.     }
  1579.     
  1580.     if (wlen > 0)
  1581.     {
  1582.         Aspnt = Asciistart;
  1583.         Hxpnt = 1;
  1584.         for (i=1; i<=wlen; i++)
  1585.         {
  1586.             wchr = buf[i-1];
  1587.             LocBuf[Hxpnt++] = Asciify(wchr >> 4);
  1588.             LocBuf[Hxpnt++] = Asciify(wchr);
  1589.             if ((wchr < 0x20) || (wchr == 0x7F))         // Non printable characters
  1590.             {
  1591.                 LocBuf[Aspnt++] = 0x2E;                    // Replace with a period
  1592.             } else {
  1593.                 LocBuf[Aspnt++] = wchr;
  1594.             }
  1595.         }
  1596.         LocBuf[0] = (wlen + Asciistart) + 1;
  1597.         TraceMessage(1, LocBuf);
  1598.     } else {
  1599.         TraceMessage(1, kCRMName"- No data - Actual count=0");
  1600.     }
  1601. }
  1602. #endif